package cn.xiaobai.enums;

import cn.xiaobai.service.AbstractApplication;
import cn.xiaobai.service.CommandServer;
import cn.xiaobai.utils.ScriptUtils;
import cn.xioabai.common.constant.RegStrConstant;
import cn.xioabai.common.enums.OsTypeEnum;
import cn.xioabai.common.utility.ExecuteUtil;
import cn.xioabai.common.utility.ScannerUtil;
import cn.xioabai.common.utility.SystemUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.nio.file.Paths;
import java.util.Objects;
import java.util.Scanner;
import java.util.regex.Pattern;

import static java.lang.System.out;
import static java.lang.System.err;

/**
 * 面板功能枚举
 *
 * @Author yangdaji
 * @Date 2022/11/2 0002
 * @PackageName cn.xiaobai.enums
 * @ClassName ServerFunEnum
 */
public enum ServerFunEnum implements ServerFun {

    /**
     * 退出命令面板
     */
    EXIT(0, "退出") {
        @Override
        public void execute() {
            System.exit(0);
        }
    },
    /**
     * 关闭有限网络适配器
     */
    ONE(1, "关闭以太网") {
        @Override
        public void execute() {
            // todo 关闭以太网, 且提示是否打开其他网络(wifi等), 可能存在多个适配器, 先进行查询进行提示, 通过用户交互进行选择
            String choose = adapterPanel(ETHERNET);
            if (StringUtils.isNoneBlank(choose)) {
                String commandTemplate = CmdCommandEnum.OFF_NETWORK.getCommand();
                String command = String.format(commandTemplate, choose);
                String executeCommand = ExecuteUtil.executeToString(command);
                // todo 暂时判断返回值不为null, 且字符串为空
                if (Objects.nonNull(executeCommand) && StringUtils.isBlank(executeCommand)) {
                    // 命令执行成功
                    out.println("WIFI适配器关闭成功!");
                } else {
                    out.println(executeCommand);
                }
            }
        }
    },
    /**
     * 打开有限网络适配器
     */
    TWO(2, "打开以太网") {
        @Override
        public void execute() {
            // todo 打开以太网, 查询进行提示, 用户交互进行选择
            String choose = adapterPanel(ETHERNET);
            if (StringUtils.isNoneBlank(choose)) {
                String commandTemplate = CmdCommandEnum.ON_NETWORK.getCommand();
                String command = String.format(commandTemplate, choose);
                String executeCommand = ExecuteUtil.executeToString(command);
                // todo 暂时判断返回值不为null, 且字符串为空
                if (Objects.nonNull(executeCommand) && StringUtils.isBlank(executeCommand)) {
                    // 命令执行成功
                    out.println("WIFI适配器关闭成功!");
                } else {
                    out.println(executeCommand);
                }
            }
        }
    },
    /**
     * 关闭无线网络适配器
     */
    THREE(3, "关闭WIFI") {
        @Override
        public void execute() {
            // todo 关闭wifi ,且提示是否打开其他网络(以太网等)
            String choose = adapterPanel(WIFI);
            if (StringUtils.isNoneBlank(choose)) {
                String commandTemplate = CmdCommandEnum.OFF_NETWORK.getCommand();
                String command = String.format(commandTemplate, choose);
                String executeCommand = ExecuteUtil.executeToString(command);
                // todo 暂时判断返回值不为null, 且字符串为空
                if (Objects.nonNull(executeCommand) && StringUtils.isBlank(executeCommand)) {
                    // 命令执行成功
                    out.println("WIFI适配器关闭成功!");
                } else {
                    out.println(executeCommand);
                }
            }
        }
    },
    /**
     * 打开无线网络适配器
     */
    FOUR(4, "打开WIFI") {
        @Override
        public void execute() {
            // 打开wifi ,不进行连接
            // 适配器打开状态: 可以通过 ipconfig 查询到, 否则查询不到
            String choose = adapterPanel(WIFI);
            if (StringUtils.isNoneBlank(choose)) {
                String commandTemplate = CmdCommandEnum.ON_NETWORK.getCommand();
                String command = String.format(commandTemplate, choose);
                String executeCommand = ExecuteUtil.executeToString(command);
                // todo 暂时判断返回值不为null, 且字符串为空
                if (Objects.nonNull(executeCommand) && StringUtils.isBlank(executeCommand)) {
                    // 命令执行成功
                    out.println("WIFI适配器打开成功!");
                } else {
                    out.println(executeCommand);
                }
            }


        }
    },
    /**
     * 打开网络控制面板
     */
    FIVE(5, "启动网络连接控制面板") {
        @Override
        public void execute() {
            // 打开网络控制面板
            String command = CmdCommandEnum.ON_NETWORK_ADAPTER_PANEL.getCommand();
            ExecuteUtil.executeToString(command);
        }
    },
    /**
     * 编辑 hosts 文件
     */
    SIX(6, "修改系统hosts文件") {
        @Override
        public void execute() {
            // 记事本打开hosts 文件
            String command = CmdCommandEnum.UPDATE_SYSTEM_HOST.getCommand();
            ExecuteUtil.executeToString(command);
        }
    },
    /**
     * 生成防火墙脚本
     */
    SEVEN(7, "防火墙白名单生成") {
        @Override
        public void execute() {
            boolean os = false;
            boolean ipStat = false;
            boolean portStat = false;
            boolean pathStat = false;
            String osType;
            OsTypeEnum osName = null;
            while (true) {
                if (!os) {
                    out.print("\n请输入系统类型(不填则自动识别当前系统):");
                    osType = getSc().nextLine().trim();
                    if (StringUtils.isBlank(osType)) {
                        osType = SystemUtils.getOsType();
                        osName = OsTypeEnum.matchType(osType);
                    } else {
                        osName = OsTypeEnum.matchType(osType);
                        if (osName == null) {
                            // 未知的系统类型, 继续输入
                            err.println("未知的系统类型,请重新输入!");
                            continue;
                        }
                    }
                    os = true;
                }
                if (!ipStat) {
                    out.print("\n请输入ip(可提供存放ip的文件所在位置):");
                    String ip = getSc().nextLine().trim();
                    boolean legal = osTypePathMatch(osName, ip);
                    if (legal) {
                        // 路径输入
                        readFile(ip, "ip");
                    } else {
                        boolean ipLegal = Pattern.matches(RegStrConstant.ipRegstr, ip);
                        if (ipLegal) {
                            // 该ip合法, 可用
                            ipList.add(ip);
                        } else {
                            // 不合法, 继续输入
                            err.println("该ip不合法,请重新输入!(例: ip格式: xx.xx.xx.xx, 如: 1.1.1.1)");
                            continue;
                        }
                    }
                    ipStat = true;
                }
                if (!portStat) {
                    out.print("\n请输入端口(可提供存放端口的文件所在位置):");
                    String port = getSc().nextLine().trim();
                    boolean legal = osTypePathMatch(osName, port);
                    if (legal) {
                        readFile(port, "port");
                    } else {
                        boolean portLegal = Pattern.matches(RegStrConstant.portRegstr, port);
                        if (portLegal) {
                            // 该ip合法, 可用
                            portList.add(port);
                        } else {
                            // 不合法, 继续输入
                            err.println("该端口不合法,请重新输入!(例: 端口范围: 0-6535)");
                            continue;
                        }
                    }
                    portStat = true;
                }
                if (!pathStat) {
                    out.print("\n请输入最终文件生成位置:");
                    String saveFilePath = getSc().nextLine().trim();
                    boolean legal = osTypePathMatch(osName, saveFilePath);
                    if (legal) {
                        File file = Paths.get(saveFilePath).toFile();
                        if (!file.exists()) {
                            file.mkdirs();
                        }
                        String path = file.getPath();
                        // 根据系统类型生成对应的批处理文件
                        whiteInventory.setFilePath(path);
                        break;
                    } else {
                        err.println("请检查输入的目录是否正确! (例: Window 下路径格式: C:\\desktop\\file, Linux 下路径格式: /home/data )");
                    }
                }
            }
            whiteInventory.setOsType(osName);
            whiteInventory.setIpList(ipList);
            whiteInventory.setPortList(portList);

            // 进行生成脚本文件到指定的位置
            ScriptUtils.generateScriptByOsType(whiteInventory);
            clearData();
            out.println("生成完毕, 文件所在目录: " + Paths.get(whiteInventory.getFilePath()).toAbsolutePath());
        }
    },

    /**
     * 处理右键功能
     */
    EIGHT(8, "添加功能到右键") {
        @Override
        public void execute() {
            abstractApplication.showMessage(2);
        }
    },
    /**
     * 其他扩展功能, 待实现
     */
    OTHER(999, "其他") {
        @Override
        public void execute() {
            // todo 其他, 待扩展
        }
    };
    private Integer number;
    private String name;

    private static Scanner sc = ScannerUtil.getScanner();


    private static AbstractApplication abstractApplication;

    ServerFunEnum(Integer number, String name) {
        this.number = number;
        this.name = name;
    }

    private static final String ETHERNET = "以太网适配器";
    private static final String WIFI = "无线局域网适配器";

    /**
     * 适配器相关的提示信息
     *
     * @return 返回用户输入的选项
     */
    protected static String adapterPanel(String adapterName) {
        CommandServer commandServer = new CommandServer();
        String listAdapterCommand = CmdCommandEnum.LIST_ADAPTER.getCommand();
        out.print("请输入适配器的名称(可回车进行查询):");
        String nextLine = getSc().nextLine().trim();
        String choose = null;
        // 输入适配器名称,进行查询,存在多个则进行展示进行选择
        if (StringUtils.isNoneBlank(nextLine)) {
            String statusByName = commandServer.queryNetworkStatusByName(nextLine, listAdapterCommand);
            if (StringUtils.isNoneBlank(statusByName)) {
                out.println("--------------匹配到的所有适配器----------");
                out.println(statusByName);
                out.println("--------------------------------------");
                out.print("请选择适配器名称:");
                choose = getSc().nextLine().trim();
            } else {
                out.println("--------------未匹配到适配器!----------");
            }
        } else {
            String statusByName = commandServer.queryNetworkStatusByName(adapterName, listAdapterCommand);
            out.println("--------------查询到的所有适配器如下:----------");
            out.println(statusByName);
            out.println("--------------------------------------");
            out.print("请选择适配器名称:");
            choose = getSc().nextLine().trim();
        }
        return choose;
    }

    /**
     * 根据系统类型, 进行检查文件路径是否正常
     *
     * @param osName
     * @param path
     * @return
     */
    protected static Boolean osTypePathMatch(OsTypeEnum osName, String path) {
        boolean legal = false;
        if (OsTypeEnum.WINDOWS.equals(osName)) {
            legal = Pattern.matches(RegStrConstant.windowPathRegstr, path);
        } else if (OsTypeEnum.LINUX.equals(osName)) {
            legal = Pattern.matches(RegStrConstant.linuxPathRegstr, path);
        } else {
            err.println("----------未识别到系统类型,或者可能没有对于该系统的适配!");
        }
        return legal;
    }

    /**
     * 对应的执行方法
     */
    public abstract void execute();

    public static ServerFunEnum getItem(Integer number) {
        for (ServerFunEnum item : values()) {
            if (item.getNumber().equals(number)) {
                return item;
            }
        }
        return null;
    }

    public Integer getNumber() {
        return number;
    }

    public String getName() {
        return name;
    }

    public static Scanner getSc() {
        return sc;
    }

    public static void setAbstractApplication(AbstractApplication abstractApplication) {
        ServerFunEnum.abstractApplication = abstractApplication;
    }
}
